#include "StdAfx.h"
#include <math.h>

#include "CeBrain.h"

CeBrain::CeBrain(void)
{
	m_pNervusMap = NULL;
	m_pNervusValues = NULL;
	m_nNervusValuesCount = 0;
}


CeBrain::~CeBrain(void)
{
}

void CeBrain::ClearNervusMap( void )
{
	delete m_pNervusMap;
	m_pNervusMap = NULL;
}

void CeBrain::BuildNervusMap( void )
{
	if( m_pNervusMap==NULL )
		m_pNervusMap = new CNervusMap();

	for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
		for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		{
			NervusPOS pos = {i,j};
			m_pNervusMap->CreateNervusAtPos( pos );
		}

	for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
		for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		{
			NervusPOS pos = {i,j};
			NervusPOS posTarget;
			for( int k=0; k<NERVUS_ANTENNA_NUM; k++ )
			{
				if( k==0 )
				{
					posTarget.nColumn = i;
					posTarget.nRow = j+1>=NERVUS_MAP_DEPTH ? 0 : j+1;
					if( j==NERVUS_MAP_DEPTH-1 )
						continue; //ignore for output pin.
				}
				else if( k== 1 )
				{
					posTarget.nColumn = i+1>=NERVUS_MAP_WIDTH ? 0 : i+1;
					posTarget.nRow = j+1>=NERVUS_MAP_DEPTH ? 0 : j+1;
				}
				else if( k== 2 )
				{
					posTarget.nColumn = i+1>=NERVUS_MAP_WIDTH ? 0 : i+1;
					posTarget.nRow = j;
				}
				
				//TRACE( "connect from {%d,%d}, %d, to {%d,%d}\n", pos.nColumn, pos.nRow, k, posTarget.nColumn, posTarget.nRow );
				m_pNervusMap->ConnectNervus( pos, k, posTarget );
			}
		}

	m_pNervusMap->GetNervus( 0, 5 )->Connect( 0, &m_pinOutput[0] );
	m_pNervusMap->GetNervus( 1, 5 )->Connect( 0, &m_pinOutput[1] );
	m_pNervusMap->GetNervus( 2, 5 )->Connect( 0, &m_pinOutput[2] );
	m_pNervusMap->GetNervus( 3, 5 )->Connect( 0, &m_pinOutput[3] );

	m_pinInput[0].Connect( m_pNervusMap->GetNervus( 0, 0 )->FindEmptyInputAntennna() );
	m_pinInput[1].Connect( m_pNervusMap->GetNervus( 1, 0 )->FindEmptyInputAntennna() );
	m_pinInput[2].Connect( m_pNervusMap->GetNervus( 2, 0 )->FindEmptyInputAntennna() );
}

bool CeBrain::RunTrainingCase( int nIdx )
{
	for( int i=0; i<OUTPUT_SIGNAL_COUNT; i++ )
		m_nOutputSignal[i] = 0;

	CTrainingCase* pCase = m_pTrainingCaseDB->GetCase( nIdx );

	for( int i=0; i<MAX_RUN_STEP; i++ )
	{
		for( int j=0; j<INPUT_SIGNAL_COUNT; j++ )
		{
			m_pinInput[j].SetSignal( pCase->GetSignalForNervus( j ) );
			//TRACE( "-->%d:%d", j, m_pinInput[j].ReadCurrentSignal());
			m_pinInput[j].TransmitSignal();
		}
		//TRACE("\n");

		m_pNervusMap->ProcessSignal();

		if( i>MAX_RUN_STEP-ALL_DIRECTION_COUNT )
		{
			for( int k=0; k<OUTPUT_SIGNAL_COUNT; k++ )
			{
				//m_nOutputSignal[i] += m_pinOutput[i].GetSignal();
				if( m_pinOutput[k].GetSignal().Model() > NERVUS_MODEL_LEVEL )
					m_nOutputSignal[k] ++;
				//TRACE( "[%d: %lf],", k, m_pinOutput[k].GetSignal().Model());
			}
		}
	}
	//TRACE("\n");

	bool bResult = pCase->CompareNervusOutputSignal( m_nOutputSignal ) == RES_GOOD;
	//TRACE("[%d]result is %d;[%d %d %d %d] %d, %d\n",nIdx,bResult, m_nOutputSignal[0], m_nOutputSignal[1], m_nOutputSignal[2], m_nOutputSignal[3], (m_nOutputSignal[0] - m_nOutputSignal[2]), m_nOutputSignal[1] - m_nOutputSignal[3]);
	//TRACE("[%d]result is %d;[%lf %lf %lf] \n",nIdx,bResult, m_nOutputSignal[0].Model(), m_nOutputSignal[1].Model(), m_nOutputSignal[2].Model() );
	return bResult;
}

float CeBrain::RunAllTrainingCase( double tryValue )
{
	float fPassRate = 0;

	{
		m_pTrainingCaseDB = new CTrainingCaseDB();
		m_pTrainingCaseDB->BuildAllCase();

		int nOkCount = 0;
		for( int i=0; i<MAX_CASE; i++ )
		{
			BuildNervusMap();
			//m_pNervusMap->GetNervus( 0, 2 )->SetValue( 0.12, 0.09 );
			//m_pNervusMap->GetNervus( 1, 2 )->SetValue( 0.14, d );
			for( int j=0; j<m_nNervusValuesCount; j++ )
			{
				m_pNervusMap->GetNervus( m_pNervusValues[j].pos.nColumn, m_pNervusValues[j].pos.nRow )
					->SetValue( 
					m_pNervusValues[j].value_real == 0.0 ? tryValue : m_pNervusValues[j].value_real,
					m_pNervusValues[j].value_image == 0.0 ? tryValue : m_pNervusValues[j].value_image );
			}

			if( RunTrainingCase( i ) )
				nOkCount++;
			ClearNervusMap();
		}
		fPassRate = ((float)nOkCount)/MAX_CASE*100;
		TRACE( "Case Pass %d, when try %lf, pass rate: %f%%\n", nOkCount, tryValue, fPassRate );

		delete m_pTrainingCaseDB;
		return fPassRate;

	}
}

void CNervusMap::ProcessSignal( void )
{
	for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
			if( m_pNervusPool[i][j] )
				m_pNervusPool[i][j]->ProcessSignal();

	for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
			if( m_pNervusPool[i][j] )
			{
				//TRACE("[%d,%d]", i, j);
				m_pNervusPool[i][j]->DoSignalTransmition();
			}
	//TRACE("\n");

}
